Finally reached Annex code in this conversion.
Sponsored-by: Graham Spencer
(
withFile,
openFile,
+ openBinaryFile,
readFile,
readFile',
writeFile,
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
O.openFile f' m
+openBinaryFile :: OsPath -> IOMode -> IO Handle
+openBinaryFile f m = do
+ f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
+ O.openBinaryFile f' m
+
readFile :: OsPath -> IO L.ByteString
readFile f = do
f' <- toOsPath <$> convertToWindowsNativeNamespace (fromOsPath f)
openFile :: OsPath -> IOMode -> IO Handle
openFile = System.IO.openFile . fromRawFilePath
+openBinaryFile :: OsPath -> IOMode -> IO Handle
+openBinaryFile = System.IO.openBinaryFile . fromRawFilePath
+
readFile :: OsPath -> IO L.ByteString
readFile = L.readFile . fromRawFilePath
#endif
import System.PosixCompat.Files (FileStatus)
import qualified Utility.RawFilePath as R
+import Utility.OsPath
type FileSize = Integer
- FileOffset which maxes out at 2 gb.
- See https://github.com/jystic/unix-compat/issues/16
-}
-getFileSize :: R.RawFilePath -> IO FileSize
+getFileSize :: OsPath -> IO FileSize
#ifndef mingw32_HOST_OS
-getFileSize f = fmap (fromIntegral . fileSize) (R.getFileStatus f)
+getFileSize f = fmap (fromIntegral . fileSize) (R.getFileStatus (fromOsPath f))
#else
-getFileSize f = bracket (F.openFile (toOsPath f) ReadMode) hClose hFileSize
+getFileSize f = bracket (F.openFile f ReadMode) hClose hFileSize
#endif
{- Gets the size of the file, when its FileStatus is already known.
-
- On windows, uses getFileSize. Otherwise, the FileStatus contains the
- size, so this does not do any work. -}
-getFileSize' :: R.RawFilePath -> FileStatus -> IO FileSize
+getFileSize' :: OsPath -> FileStatus -> IO FileSize
#ifndef mingw32_HOST_OS
getFileSize' _ s = return $ fromIntegral $ fileSize s
#else
withTmpFile (toOsPath "gpg") $ \tmpfile h -> do
liftIO $ B.hPutStr h passphrase
liftIO $ hClose h
- let passphrasefile = [Param "--passphrase-file", File (fromRawFilePath (fromOsPath tmpfile))]
+ let passphrasefile = [Param "--passphrase-file", File (fromOsPath tmpfile)]
go $ passphrasefile ++ params
#endif
where
go Nothing = return Nothing
makenewdir n = do
- let subdir = tmpdir </> show n
+ let subdir = toOsPath tmpdir </> toOsPath (show n)
catchIOErrorType AlreadyExists (const $ makenewdir $ n + 1) $ do
createDirectory subdir
return subdir
import Utility.TimeStamp
import Utility.QuickCheck
import qualified Utility.RawFilePath as R
+import qualified Utility.FileIO as F
import System.PosixCompat.Types
import System.PosixCompat.Files (isRegularFile, fileID)
return $ InodeCache $ InodeCachePrim i sz (MTimeHighRes t)
_ -> Nothing
-genInodeCache :: RawFilePath -> TSDelta -> IO (Maybe InodeCache)
+genInodeCache :: OsPath -> TSDelta -> IO (Maybe InodeCache)
genInodeCache f delta = catchDefaultIO Nothing $
- toInodeCache delta f =<< R.getSymbolicLinkStatus f
+ toInodeCache delta f =<< R.getSymbolicLinkStatus (fromOsPath f)
-toInodeCache :: TSDelta -> RawFilePath -> FileStatus -> IO (Maybe InodeCache)
+toInodeCache :: TSDelta -> OsPath -> FileStatus -> IO (Maybe InodeCache)
toInodeCache d f s = toInodeCache' d f s (fileID s)
-toInodeCache' :: TSDelta -> RawFilePath -> FileStatus -> FileID -> IO (Maybe InodeCache)
+toInodeCache' :: TSDelta -> OsPath -> FileStatus -> FileID -> IO (Maybe InodeCache)
toInodeCache' (TSDelta getdelta) f s inode
| isRegularFile s = do
delta <- getdelta
sz <- getFileSize' f s
#ifdef mingw32_HOST_OS
- mtime <- utcTimeToPOSIXSeconds <$> getModificationTime (fromRawFilePath f)
+ mtime <- utcTimeToPOSIXSeconds <$> getModificationTime f
#else
let mtime = Posix.modificationTimeHiRes s
#endif
- Its InodeCache at the time of its creation is written to the cache file,
- so changes can later be detected. -}
data SentinalFile = SentinalFile
- { sentinalFile :: RawFilePath
- , sentinalCacheFile :: RawFilePath
+ { sentinalFile :: OsPath
+ , sentinalCacheFile :: OsPath
}
deriving (Show)
writeSentinalFile :: SentinalFile -> IO ()
writeSentinalFile s = do
- writeFile (fromRawFilePath (sentinalFile s)) ""
- maybe noop (writeFile (fromRawFilePath (sentinalCacheFile s)) . showInodeCache)
+ F.writeFile' (sentinalFile s) mempty
+ maybe noop (writeFile (fromOsPath (sentinalCacheFile s)) . showInodeCache)
=<< genInodeCache (sentinalFile s) noTSDelta
data SentinalStatus = SentinalStatus
Just new -> return $ calc old new
where
loadoldcache = catchDefaultIO Nothing $
- readInodeCache <$> readFile (fromRawFilePath (sentinalCacheFile s))
+ readInodeCache <$> readFile (fromOsPath (sentinalCacheFile s))
gennewcache = genInodeCache (sentinalFile s) noTSDelta
calc (InodeCache (InodeCachePrim oldinode oldsize oldmtime)) (InodeCache (InodeCachePrim newinode newsize newmtime)) =
SentinalStatus (not unchanged) tsdelta
dummy = SentinalStatus True noTSDelta
sentinalFileExists :: SentinalFile -> IO Bool
-sentinalFileExists s = allM R.doesPathExist [sentinalCacheFile s, sentinalFile s]
+sentinalFileExists s = allM doesPathExist [sentinalCacheFile s, sentinalFile s]
instance Arbitrary InodeCache where
arbitrary =
where
go num
| num > maxLogs = return ()
- | otherwise = whenM (doesFileExist currfile) $ do
+ | otherwise = whenM (doesFileExist (toOsPath currfile)) $ do
go (num + 1)
rename (toRawFilePath currfile) (toRawFilePath nextfile)
where
{- Lists most recent logs last. -}
listLogs :: FilePath -> IO [FilePath]
-listLogs logfile = filterM doesFileExist $ reverse $
+listLogs logfile = filterM (doesFileExist . toOsPath) $ reverse $
logfile : map (rotatedLog logfile) [1..maxLogs]
maxLogs :: Int
import Common
import BuildInfo
import Utility.Env.Set
+import qualified Utility.OsString as OS
import System.Posix.Types
- path where the program was found. Make sure at runtime that lsof is
- available, and if it's not in PATH, adjust PATH to contain it. -}
setup :: IO ()
-setup = do
- let cmd = fromMaybe "lsof" BuildInfo.lsof
- when (isAbsolute cmd) $ do
- path <- getSearchPath
- let path' = takeDirectory cmd : path
- setEnv "PATH" (intercalate [searchPathSeparator] path') True
+setup = when (isAbsolute cmd) $ do
+ path <- getSearchPath
+ let path' = fromOsPath $ OS.intercalate sep $
+ takeDirectory cmd : path
+ setEnv "PATH" path' True
+ where
+ cmd = toOsPath $ fromMaybe "lsof" BuildInfo.lsof
+ sep = OS.singleton searchPathSeparator
{- Checks each of the files in a directory to find open files.
- Note that this will find hard links to files elsewhere that are open. -}
-}
watchFileSize
:: (MonadIO m, MonadMask m)
- => RawFilePath
+ => OsPath
-> MeterUpdate
-> (MeterUpdate -> m a)
-> m a
import qualified Utility.RawFilePath as R
import Utility.Hash (IncrementalVerifier(..))
import Utility.Url.Parse
+import qualified Utility.FileIO as F
import Network.URI
import Network.HTTP.Types
=<< curlRestrictedParams r u defport (basecurlparams url')
existsfile u = do
- let f = toRawFilePath (unEscapeString (uriPath u))
- s <- catchMaybeIO $ R.getSymbolicLinkStatus f
+ let f = toOsPath (unEscapeString (uriPath u))
+ s <- catchMaybeIO $ R.getSymbolicLinkStatus (fromOsPath f)
case s of
Just stat -> do
sz <- getFileSize' f stat
-
- When the download fails, returns an error message.
-}
-download :: MeterUpdate -> Maybe IncrementalVerifier -> URLString -> FilePath -> UrlOptions -> IO (Either String ())
+download :: MeterUpdate -> Maybe IncrementalVerifier -> URLString -> OsPath -> UrlOptions -> IO (Either String ())
download = download' False
-download' :: Bool -> MeterUpdate -> Maybe IncrementalVerifier -> URLString -> FilePath -> UrlOptions -> IO (Either String ())
+download' :: Bool -> MeterUpdate -> Maybe IncrementalVerifier -> URLString -> OsPath -> UrlOptions -> IO (Either String ())
download' nocurlerror meterupdate iv url file uo =
catchJust matchHttpException go showhttpexception
`catchNonAsync` (dlfailed . show)
-- curl does not create destination file
-- if the url happens to be empty, so pre-create.
unlessM (doesFileExist file) $
- writeFile file ""
- ifM (boolSystem "curl" (curlparams ++ [Param "-o", File file, File rawurl]))
+ F.writeFile file mempty
+ ifM (boolSystem "curl" (curlparams ++ [Param "-o", File (fromOsPath file), File rawurl]))
( return $ Right ()
, return $ Left "download failed"
)
noverification
let src = unEscapeString (uriPath u)
withMeteredFile src meterupdate $
- L.writeFile file
+ F.writeFile file
return $ Right ()
-- Conduit does not support ftp, so will throw an exception on a
- thrown for reasons other than http status codes will still be thrown
- as usual.)
-}
-downloadConduit :: MeterUpdate -> Maybe IncrementalVerifier -> Request -> FilePath -> UrlOptions -> IO ()
+downloadConduit :: MeterUpdate -> Maybe IncrementalVerifier -> Request -> OsPath -> UrlOptions -> IO ()
downloadConduit meterupdate iv req file uo =
- catchMaybeIO (getFileSize (toRawFilePath file)) >>= \case
+ catchMaybeIO (getFileSize file) >>= \case
Just sz | sz > 0 -> resumedownload sz
_ -> join $ runResourceT $ do
liftIO $ debug "Utility.Url" (show req')
=> MeterUpdate
-> Maybe IncrementalVerifier
-> BytesProcessed
- -> FilePath
+ -> OsPath
-> IOMode
-> Response (ConduitM () B8.ByteString m ())
-> m ()
return (const noop)
(Just iv', _) -> return (updateIncrementalVerifier iv')
(Nothing, _) -> return (const noop)
- (fr, fh) <- allocate (openBinaryFile file mode) hClose
+ (fr, fh) <- allocate (F.openBinaryFile file mode) hClose
runConduit $ responseBody resp .| go ui initialp fh
release fr
where
Make Utility.SystemDirectory import it when built with OsPath,
and the remaining 6 hours or work will explain itself..
This has been started in the `ospath` branch.
+* As part of the OsPath conversion, Git.LsFiles has several
+ `pipeNullSplit'` calls that have toOsPath mapped over the results.
+ That adds an additional copy, so the lazy ByteString is converted to strict,
+ and then to ShortByteString, with a copy each time. This is in the
+ critical path for large git repos, and might be a noticable slowdown.
+ There is currently no easy way to go direct from a lazy ByteString to a
+ ShortByteString, although it would certianly be possible to write low
+ level code to do it efficiently. Alternatively, it would be possible to
+ read a strict ByteString direct from a handle, like hGetLine does
+ (although in this case it would need to stop at the terminating 0 byte)
+ and unsafePerformIO to stream to a list would avoid needing to rewrite
+ this code to not use a list.
[[!tag confirmed]]